
package com.hlkj.pay.app.finance.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.finance.IFinanceOrderAppService;
import com.hlkj.pay.app.finance.IFinanceRecordAppService;
import com.hlkj.pay.app.merchant.IMerchantConfigAppService;
import com.hlkj.pay.app.merchant.impl.MerchantFeeParamsCheck;
import com.hlkj.pay.app.order.IAcctOrderAppService;
import com.hlkj.pay.app.order.impl.OrderHandler;
import com.hlkj.pay.app.order.impl.OrderNotifyHandler;
import com.hlkj.pay.dto.common.OrderStatusDto;
import com.hlkj.pay.dto.merchant.ProviderChannelFeeConfigList;
import com.hlkj.pay.dto.merchant.config.MerchantPaymentConfigDto;
import com.hlkj.pay.dto.merchant.config.MerchantReportConfigDto;
import com.hlkj.pay.dto.provider.DefaultFeeConfig;
import com.hlkj.pay.dto.provider.StepFeeConfig;
import com.hlkj.pay.enums.*;
import com.hlkj.pay.infrastructure.model.finance.MerchantFinanceRecordDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantConfigDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantInfoDO;
import com.hlkj.pay.infrastructure.model.order.OrderFeeResultDO;
import com.hlkj.pay.infrastructure.model.order.OrderWithdrawDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.order.RefundOrderDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelFeeConfigDO;
import com.hlkj.pay.infrastructure.model.payment.MerchantPaymentDO;
import com.hlkj.pay.infrastructure.model.payment.MerchantPaymentDetailDO;
import com.hlkj.pay.service.finance.IMerchantFinanceRecordService;
import com.hlkj.pay.service.merchant.IMerchantConfigService;
import com.hlkj.pay.service.merchant.IMerchantService;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.service.order.IRefundOrderService;
import com.hlkj.pay.service.order.IWithdrawOrderService;
import com.hlkj.pay.service.pay.IProviderService;
import com.hlkj.pay.service.payment.IMerchantPaymentService;
import com.hlkj.pay.util.MerchantUtils;
import com.hlkj.pay.vo.finance.req.MerchantFinanceRecordReq;
import com.hlkj.pay.vo.finance.req.MerchantFinanceRecordReturnReq;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author HlpayTeam
 * @date 2024/11/15 13:14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FinanceOrderAppServiceImpl implements IFinanceOrderAppService {

    public final IPayOrderService payOrderService;

    public final IMerchantPaymentService merchantPaymentService;

    public final IRefundOrderService refundOrderService;

    public final IMerchantService merchantService;

    public final IMerchantConfigService merchantConfigService;

    public final IMerchantConfigAppService merchantConfigAppService;

    public final IProviderService providerService;

    public final IFinanceRecordAppService financeRecordAppService;

    public final MerchantFeeParamsCheck merchantFeeParamsCheck;

    public final OrderHandler orderHandler;

    public final IAcctOrderAppService acctOrderAppService;

    public final IWithdrawOrderService withdrawOrderService;

    private final OrderNotifyHandler orderNotifyHandler;

    private final IMerchantFinanceRecordService merchantFinanceRecordService;

    @Override
    public void processOrderFeeCalculate(OrderStatusDto orderStatusDto) {
        PayOrderEnums.ORDER_STATUS_TYPE orderStatusType = PayOrderEnums.ORDER_STATUS_TYPE.from(orderStatusDto.getOrderStatusType());
        String orderNo = orderStatusDto.getOrderNo();
        if (!StringUtils.hasText(orderNo)) {
            log.info("收到的数据错误 orderNo:{}", orderNo);
            return;
        }
        switch (orderStatusType) {
            case PAY_ORDER_STATUS:
                PayOrderDO payOrderDO = payOrderService.queryPayOrderNoCache(orderNo);
                if (payOrderDO == null) {
                    log.info("收到的数据错误 订单号不存在 payOrderNo:{}", orderNo);
                    return;
                }
                MerchantInfoDO merchantInfoDO = merchantService.queryMerchant(payOrderDO.getOrderSn());
                // 余额变更
                processPayOrderFinanceRecord(payOrderDO, merchantInfoDO);
                // 内扣手续费计算
                processPayOrderChannelFee(payOrderDO, merchantInfoDO);
                // 统计
                payOrderDO = payOrderService.queryPayOrderNoCache(orderNo);
                orderHandler.sendStatistics(payOrderDO, PayOrderEnums.STATISTICS_TYPE.PAY_ORDER);
                // 分账
                acctOrderAppService.payAcctOrder(payOrderDO);
                break;
            case PAYMENT_ORDER_STATUS:
                MerchantPaymentDetailDO merchantPaymentDetailDO = merchantPaymentService.queryPaymentDetail(orderNo);
                if (merchantPaymentDetailDO == null) {
                    log.info("收到的数据错误 代付订单号不存在 payOrderNo:{}", orderNo);
                    return;
                }
                MerchantPaymentDO merchantPaymentDO = merchantPaymentService.queryDetail(merchantPaymentDetailDO.getPaymentId());

                MerchantPaymentConfigDto merchantPaymentConfigDto = merchantConfigAppService.queryPaymentConfig(merchantPaymentDetailDO.getSn());
                // 商户手续费率同步数据库
                // merchantService.syncMerchantFeeAmount(merchantPaymentDetailDO.getOrderSn());
                // 余额变更
                log.info("代付日志 processOrderFeeCalculate 明细id：{} 状态:{}", merchantPaymentDetailDO.getDetailPaymentId(), merchantPaymentDetailDO.getStatus());
                if (Objects.equals(MerchantEnum.PROCESS_STATUS.SUCCESS.getCode(), merchantPaymentDetailDO.getStatus())) {
                    processPaymentOrderFinanceRecord(merchantPaymentDO, merchantPaymentDetailDO, merchantPaymentConfigDto);
                }
                // 内扣手续费计算
                // processPayOrderChannelFee(merchantPaymentDetailDO, merchantInfoDO);
                break;
            case WITHDRAW_ORDER_STATUS:
                OrderWithdrawDO orderWithdrawDO = withdrawOrderService.queryPayOrder(orderNo);
                if (orderWithdrawDO == null) {
                    log.info("收到的数据错误 提现订单号不存在 payOrderNo:{}", orderNo);
                    return;
                }
                MerchantReportConfigDto merchantReportConfigDto = merchantConfigAppService.queryReportConfig(orderWithdrawDO.getSn());
                // 余额变更
                processReportOrderFinanceRecord(orderWithdrawDO, merchantReportConfigDto);
                // 然后回调
                orderNotifyHandler.orderNotify(orderWithdrawDO.getPayOrderNo(), 1, PayOrderEnums.ORDER_STATUS_TYPE.WITHDRAW_ORDER_STATUS);
                break;
            case REFUND_STATUS:
                processRefundOrder(orderNo);
                break;
        }
    }

    private void processReportOrderFinanceRecord(OrderWithdrawDO orderWithdrawDO, MerchantReportConfigDto merchantReportConfigDto) {
        // 1: 单笔费率 2: 单笔固定 3: 费率+固定
        if (merchantReportConfigDto == null || !CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantReportConfigDto.getChargeType())) {
            log.info("汇电通配置方式 无需计算手续费 payOrderNo:{}, merchantPaymentConfigDto:{}", orderWithdrawDO.getPayOrderNo(), JsonUtils.toJsonString(merchantReportConfigDto));
            return;
        }
        MerchantReportConfigDto.FeeType outFeeType = merchantReportConfigDto.getOutFeeType();
        MerchantReportConfigDto.FeeType inFeeType = merchantReportConfigDto.getInFeeType();
        if (outFeeType == null && inFeeType == null) {
            log.info("汇电通 出金配置不存在 无需计算手续费 payOrderNo:{}, merchantPaymentConfigDto:{}", orderWithdrawDO.getPayOrderNo(), JsonUtils.toJsonString(merchantReportConfigDto));
            return;
        }
        BigDecimal inAmount = amount(inFeeType, orderWithdrawDO.getAmount());
        BigDecimal outAmount = amount(outFeeType, orderWithdrawDO.getAmount());
        BigDecimal amount = outAmount;
        if (inAmount != null) {
            if (amount == null) {
                amount = inAmount;
            }
            else {
                amount = MerchantUtils.add(amount, inAmount);
            }
        }
        OrderWithdrawDO updatePayOrderDO = new OrderWithdrawDO();
        updatePayOrderDO.setId(orderWithdrawDO.getId());
        if (amount == null) {
            log.info("提现金额变动为0 不记录变动记录 payOrderNo:{},feeAmount:{}", orderWithdrawDO.getPayOrderNo(), orderWithdrawDO.getAmount());
            updatePayOrderDO.setFeeAmount(new BigDecimal(0));
        }
        else {
            MerchantFinanceRecordReq merchantFinanceRecordReq = new MerchantFinanceRecordReq();
            merchantFinanceRecordReq.setSn(orderWithdrawDO.getSn());
            merchantFinanceRecordReq.setType(FinanceEnum.FINANCE_TYPE.MERCHANT_FEE.getCode());
            merchantFinanceRecordReq.setOrderNo(orderWithdrawDO.getPayOrderNo());
            merchantFinanceRecordReq.setChangeType(CommonEnum.YES_NO_TYPE.NO.getCode());
            merchantFinanceRecordReq.setAmount(MerchantUtils.bigDecimalToString(amount));
            merchantFinanceRecordReq.setRemark("提现订单扣费");
            updatePayOrderDO.setFeeAmount(amount);
            financeRecordAppService.addFinanceRecord(merchantFinanceRecordReq);
        }
        withdrawOrderService.updatePayOrderStatus(updatePayOrderDO);
    }

    BigDecimal amount(MerchantReportConfigDto.FeeType feeType, BigDecimal orderAmount) {
        if (feeType == null) {
            return null;
        }
        Integer type = feeType.getType();
        BigDecimal amount = null;
        switch (type) {
            case 1:
                if (feeType.getFee() != null) {
                    BigDecimal fee = MerchantUtils.divide(feeType.getFee(), new BigDecimal(100));
                    amount = MerchantUtils.multiply(orderAmount, fee);
                }
                break;
            case 2:
                if (feeType.getAmount() != null) {
                    amount = feeType.getAmount();
                }
                break;
            case 3:
                if (feeType.getFee() != null && feeType.getAmount() != null) {
                    BigDecimal fee = MerchantUtils.divide(feeType.getFee(), new BigDecimal(100));
                    BigDecimal feeAmount = MerchantUtils.multiply(orderAmount, fee);
                    amount = feeType.getAmount();
                    amount = MerchantUtils.add(feeAmount, amount);
                }
                break;
            default:
        }
        return amount;
    }

    void processPayOrderFinanceRecord(PayOrderDO payOrderDO, MerchantInfoDO merchantInfoDO) {
        if (payOrderDO.getFeeAmount() == null || payOrderDO.getFeeAmount().compareTo(new BigDecimal(0)) == 0) {
            log.info("金额变动为0 不记录变动记录 payOrderNo:{},feeAmount:{}", payOrderDO.getPayOrderNo(), payOrderDO.getFeeAmount());
            return;
        }
        MerchantFinanceRecordReq merchantFinanceRecordReq = new MerchantFinanceRecordReq();
        merchantFinanceRecordReq.setSn(payOrderDO.getOrderSn());
        merchantFinanceRecordReq.setAmount(MerchantUtils.bigDecimalToString(payOrderDO.getFeeAmount()));
        merchantFinanceRecordReq.setChangeType(CommonEnum.YES_NO_TYPE.NO.getCode());
        merchantFinanceRecordReq.setType(FinanceEnum.FINANCE_TYPE.MERCHANT_FEE.getCode());
        merchantFinanceRecordReq.setOrderNo(payOrderDO.getPayOrderNo());
        merchantFinanceRecordReq.setRemark("交易订单扣费");
        financeRecordAppService.addFinanceRecord(merchantFinanceRecordReq);
        processPayOrderAgentFinanceRecord(payOrderDO, merchantInfoDO.getSuperAgent(), merchantInfoDO.getCommRateBase());
    }

    void processPaymentOrderFinanceRecord(MerchantPaymentDO merchantPaymentDO, MerchantPaymentDetailDO merchantPaymentDetailDO, MerchantPaymentConfigDto merchantPaymentConfigDto) {
        // 1: 单笔费率 2: 单笔固定 3: 费率+固定
        Integer entryType = merchantPaymentDO.getEntryType();
        MerchantFinanceRecordReq merchantFinanceRecordReq = new MerchantFinanceRecordReq();
        merchantFinanceRecordReq.setSn(merchantPaymentDetailDO.getSn());
        merchantFinanceRecordReq.setType(FinanceEnum.FINANCE_TYPE.MERCHANT_FEE.getCode());
        merchantFinanceRecordReq.setOrderNo(merchantPaymentDetailDO.getDetailPaymentId());
        List<MerchantPaymentConfigDto.EntryTypConfig> entryTypConfigList = merchantPaymentConfigDto.getEntryTypes().stream()
                .filter(merchantPaymentConfig -> merchantPaymentConfig.getEntryType().equals(entryType)).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(entryTypConfigList)) {
            log.info("代付下发方式配置方式不存在 detailPaymentId:{}, entryType:{},merchantPaymentConfigDto:{}", merchantPaymentDetailDO.getDetailPaymentId(), merchantPaymentDO.getEntryType(),
                    JsonUtils.toJsonString(merchantPaymentConfigDto));
            return;
        }
        MerchantPaymentConfigDto.EntryTypConfig entryTypConfig = entryTypConfigList.get(0);
        Integer type = entryTypConfig.getType();
        BigDecimal amount = null;
        switch (type) {
            case 1:
                if (entryTypConfig.getFee() != null) {
                    BigDecimal fee = MerchantUtils.divide(entryTypConfig.getFee(), new BigDecimal(100));
                    amount = MerchantUtils.multiply(merchantPaymentDetailDO.getPayAmount(), fee);
                }
                break;
            case 2:
                if (entryTypConfig.getAmount() != null) {
                    amount = entryTypConfig.getAmount();
                }
                break;
            case 3:
                if (entryTypConfig.getFee() != null && entryTypConfig.getAmount() != null) {
                    BigDecimal fee = MerchantUtils.divide(entryTypConfig.getFee(), new BigDecimal(100));
                    BigDecimal feeAmount = MerchantUtils.multiply(merchantPaymentDetailDO.getPayAmount(), fee);
                    amount = entryTypConfig.getAmount();
                    amount = MerchantUtils.add(feeAmount, amount);
                }
                break;
            default:
        }
        if (amount == null) {
            log.info("代付金额变动为0 不记录变动记录 payOrderNo:{},feeAmount:{}", merchantPaymentDetailDO.getDetailPaymentId(), merchantPaymentDetailDO.getPayAmount());
        }
        merchantFinanceRecordReq.setChangeType(CommonEnum.YES_NO_TYPE.NO.getCode());
        if (CommonEnum.YES_NO_TYPE.NO.getCode().equals(merchantPaymentDO.getPaymentType())) {
            merchantFinanceRecordReq.setAmount(MerchantUtils.bigDecimalToString(amount));
            merchantFinanceRecordReq.setRemark("代付订单扣费");
        }
        else {
            merchantFinanceRecordReq.setRemark("代付订单充值");
            // merchantFinanceRecordReq.setChangeType(CommonEnum.YES_NO_TYPE.YES.getCode());
            merchantFinanceRecordReq.setDeductionAmount(false);
            // merchantFinanceRecordReq.setAmount(MerchantUtils.bigDecimalToString(merchantPaymentDetailDO.getPayAmount()));
            merchantFinanceRecordReq.setAmount(MerchantUtils.bigDecimalToString(amount));
        }
        //判断是否已外扣， 强制避免重复外扣
        MerchantFinanceRecordDO recordDO = merchantFinanceRecordService.getMerchantFinanceRecordDO(merchantFinanceRecordReq);
        if (recordDO == null) {
            financeRecordAppService.addFinanceRecord(merchantFinanceRecordReq);
        } else {
            log.info("代付日志 processPaymentOrderFinanceRecord 重复外扣，过滤：{} 状态:{}", merchantPaymentDetailDO.getDetailPaymentId(), merchantPaymentDetailDO.getStatus());
        }
        // todo 代理商后面处理
        // processPayOrderAgentFinanceRecord(merchantPaymentDetailDO,
        // merchantPaymentConfigDto.getSuperAgent(),
        // merchantPaymentConfigDto.getCommRateBase());
        MerchantPaymentDetailDO updateMerchantPaymentDetailDO=new MerchantPaymentDetailDO();
        updateMerchantPaymentDetailDO.setDetailPaymentId(merchantPaymentDetailDO.getDetailPaymentId());
        updateMerchantPaymentDetailDO.setFeeAmount(amount);
        merchantPaymentService.updatePaymentDetail(updateMerchantPaymentDetailDO);
    }

    void processPayOrderAgentFinanceRecord(PayOrderDO payOrderDO, String superAgent, BigDecimal commRateBase) {
        if (!StringUtils.hasText(superAgent)) {
            return;
        }
        MerchantInfoDO agentInfoDO = merchantService.queryMerchant(superAgent);
        if (agentInfoDO.getCommRateBase().compareTo(commRateBase) >= 0) {
            return;
        }

        // 外扣手续费
        BigDecimal feeAmount = MerchantUtils.calculateFeeUp(payOrderDO.getAmount(), commRateBase.subtract(agentInfoDO.getCommRateBase()));
        MerchantFinanceRecordReq merchantFinanceRecordReq = new MerchantFinanceRecordReq();
        merchantFinanceRecordReq.setSn(superAgent);
        merchantFinanceRecordReq.setAmount(MerchantUtils.bigDecimalToString(feeAmount));
        merchantFinanceRecordReq.setChangeType(CommonEnum.YES_NO_TYPE.YES.getCode());
        merchantFinanceRecordReq.setType(FinanceEnum.FINANCE_TYPE.MERCHANT_FEE.getCode());
        merchantFinanceRecordReq.setOrderNo(payOrderDO.getPayOrderNo());
        financeRecordAppService.addFinanceRecord(merchantFinanceRecordReq);
        // 继续循环处理
        processPayOrderAgentFinanceRecord(payOrderDO, agentInfoDO.getSuperAgent(), agentInfoDO.getCommRateBase());
    }

    void processPayOrderChannelFee(PayOrderDO payOrderDO, MerchantInfoDO merchantInfoDO) {
        MerchantConfigDO merchantConfigDO = merchantConfigService.queryConfig(payOrderDO.getOrderSn());
        // 商户费率
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = merchantConfigDO.getMerchantFeeConfigList();
        // 商户费率
        ProviderChannelFeeConfigList merchantFeeConfig = merchantFeeConfigList.stream().filter(agentConfig -> agentConfig.getPayWayCode().equals(payOrderDO.getPayWayCode()))
                .collect(Collectors.toList()).stream().findFirst().orElse(null);
        // 服务商费率
        ProviderChannelFeeConfigDO providerChannelFeeConfigDO = null;
        List<String> errorMsg = new ArrayList<>();
        if (StringUtils.hasText(merchantInfoDO.getSuperAgent())) {
            MerchantConfigDO agentConfigDO = merchantConfigService.queryConfig(payOrderDO.getOrderSn());
            List<ProviderChannelFeeConfigList> agentFeeConfigList = agentConfigDO.getMerchantFeeConfigList();
            // 代理费率
            ProviderChannelFeeConfigList agentFeeConfig = agentFeeConfigList.stream().filter(agentConfig -> agentConfig.getPayWayCode().equals(payOrderDO.getPayWayCode()))
                    .collect(Collectors.toList()).stream().findFirst().orElse(null);
            if (agentFeeConfig == null) {
                errorMsg.add("该交易商户存在上级代理商,代理商未配置" + payOrderDO.getPayWayCode() + "费率");
            }
            else {
                // 代理与商户直接配置校验
                List<String> errorMsgList = merchantFeeParamsCheck.checkAgentAndMerchantFeeConfig(agentFeeConfig, merchantFeeConfig);
                if (CollectionUtils.isEmpty(errorMsgList)) {
                    errorMsg.addAll(errorMsg);
                }
            }
        }
        // 服务商费率
        List<ProviderChannelFeeConfigDO> providerFeeConfigList = providerService.queryFeeConfig(payOrderDO.getProviderCode(), payOrderDO.getChannelCode());
        providerChannelFeeConfigDO = providerFeeConfigList.stream().filter(agentConfig -> agentConfig.getPayWayCode().equals(payOrderDO.getPayWayCode()))
                .collect(Collectors.toList()).stream().findFirst().orElse(null);

        if (providerChannelFeeConfigDO == null) {
            errorMsg.add("该交易商户服务商未配置" + payOrderDO.getPayWayCode() + "费率");
        }
        else {

            if (merchantFeeConfig == null) {
                errorMsg.add("该交易商户费率未配置" + payOrderDO.getPayWayCode() + "费率");
            }
            else {
                // 代理与商户直接配置校验
                List<String> errorMsgList = merchantFeeParamsCheck.checkProviderAndMerchantFeeConfig(providerChannelFeeConfigDO, merchantFeeConfig);
                if (CollectionUtils.isEmpty(errorMsgList)) {
                    errorMsg.addAll(errorMsg);
                }
            }
        }
        if (StringUtils.hasText(merchantInfoDO.getSuperAgent())) {
            MerchantConfigDO agentConfigDO = merchantConfigService.queryConfig(payOrderDO.getOrderSn());
            List<ProviderChannelFeeConfigList> agentFeeConfigList = agentConfigDO.getMerchantFeeConfigList();
            // 代理费率
            ProviderChannelFeeConfigList agentFeeConfig = agentFeeConfigList.stream().filter(agentConfig -> agentConfig.getPayWayCode().equals(payOrderDO.getPayWayCode()))
                    .collect(Collectors.toList()).stream().findFirst().orElse(null);
            if (agentFeeConfig == null) {
                errorMsg.add("该交易商户存在上级代理商,代理商未配置" + payOrderDO.getPayWayCode() + "费率");
            }
            else {
                // 代理与商户直接配置校验
                List<String> errorMsgList = merchantFeeParamsCheck.checkAgentAndMerchantFeeConfig(agentFeeConfig, merchantFeeConfig);
                if (CollectionUtils.isEmpty(errorMsgList)) {
                    errorMsg.addAll(errorMsg);
                }
            }
        }
        if (!CollectionUtils.isEmpty(errorMsg)) {
            OrderFeeResultDO orderFeeResultDO = new OrderFeeResultDO();
            orderFeeResultDO.setOrderNo(payOrderDO.getPayOrderNo());
            orderFeeResultDO.setType(PayOrderEnums.ORDER_STATUS_TYPE.PAY_ORDER_STATUS.getCode());
            orderFeeResultDO.setAmount(payOrderDO.getAmount());
            orderFeeResultDO.setFeeRate(payOrderDO.getFeeRate());
            orderFeeResultDO.setFeeAmount(payOrderDO.getFeeAmount());
            orderFeeResultDO.setChannelFeeRate(null);
            orderFeeResultDO.setChannelFeeAmount(null);
            orderFeeResultDO.setStatus(CommonEnum.YES_NO_TYPE.NO.getCode());
            orderFeeResultDO.setMessage(JsonUtils.toJsonString(errorMsg));
            payOrderService.addOrderFeeResult(orderFeeResultDO);
            return;
        }
        OrderFeeResultDO orderFeeResultDO = processMerchantCalculate(payOrderDO, merchantFeeConfig);
        if (orderFeeResultDO == null) {
            log.info("订单内扣手续费计算错误,商户支付方式手续费未配置 payOrderNo:{}, sn:{}, payWayCode:{}", payOrderDO.getPayOrderNo(), payOrderDO.getOrderSn(), payOrderDO.getPayWayCode());
            return;
        }
        PayOrderDO updatePayOrderDO = new PayOrderDO();
        updatePayOrderDO.setId(payOrderDO.getId());
        updatePayOrderDO.setChannelFeeRate(orderFeeResultDO.getChannelFeeRate());
        updatePayOrderDO.setChannelFeeAmount(orderFeeResultDO.getChannelFeeAmount());
        updatePayOrderDO.setFeeTime(System.currentTimeMillis());
        // 更新渠道手续费金额
        payOrderService.updatePayOrder(updatePayOrderDO, payOrderDO.getPayOrderNo(), payOrderDO.getOrderSn(), payOrderDO.getMchOrderNo());
        // 处理结果
        payOrderService.addOrderFeeResult(orderFeeResultDO);
        // 更新结果 统计需要
        payOrderDO.setChannelFeeRate(orderFeeResultDO.getChannelFeeRate());
        payOrderDO.setChannelFeeAmount(orderFeeResultDO.getChannelFeeAmount());
        payOrderDO.setFeeTime(System.currentTimeMillis());
    }

    /**
     * 
     * @param payOrderDO
     * @param providerChannelFeeConfigDO
     * @return
     */
    OrderFeeResultDO processCalculate(PayOrderDO payOrderDO, ProviderChannelFeeConfigDO providerChannelFeeConfigDO) {
        OrderFeeResultDO orderFeeResultDO = new OrderFeeResultDO();

        // 机构手续费费率
        BigDecimal channelFeeRate = null;
        // 机构交易手续费
        BigDecimal channelFeeAmount = null;
        if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(providerChannelFeeConfigDO.getStepFeeType())) {
            List<StepFeeConfig> stepFeeConfigs = providerChannelFeeConfigDO.getStepFeeConfigs();
            for (StepFeeConfig stepFeeConfig : stepFeeConfigs) {
                boolean amountInRange = isAmountInRange(payOrderDO.getAmount(), stepFeeConfig.getStartAmt(), stepFeeConfig.getEndAmt());
                if (amountInRange) {
                    channelFeeRate = stepFeeConfig.getRateBase();
                    break;
                }
            }
        }
        // 最后才是基础费率
        if (channelFeeAmount == null) {
            DefaultFeeConfig defaultFeeConfigValue = providerChannelFeeConfigDO.getDefaultFeeConfigValue();
            PayEnums.FEE_TYPE feeType = PayEnums.FEE_TYPE.from(defaultFeeConfigValue.getFeeType());
            switch (feeType) {
                case FIXED_VALUE:
                    channelFeeAmount = defaultFeeConfigValue.getFixedRate();
                    break;
                case PERCENTAGE:
                    channelFeeRate = defaultFeeConfigValue.getRateBase();
                    break;
                default:
                    BigDecimal multiply = payOrderDO.getAmount().multiply(defaultFeeConfigValue.getRateBase());
                    if (multiply.compareTo(defaultFeeConfigValue.getFixedRate()) > 0) {
                        channelFeeAmount = defaultFeeConfigValue.getFixedRate();
                        channelFeeRate = defaultFeeConfigValue.getRateBase();
                    }
                    else {
                        channelFeeAmount = defaultFeeConfigValue.getFixedRate();
                    }

            }
        }
        if (channelFeeRate != null && channelFeeAmount == null) {
            channelFeeAmount = MerchantUtils.calculateFeeUp(payOrderDO.getAmount(), channelFeeRate);
        }
        if (channelFeeRate == null && channelFeeAmount != null) {
            channelFeeRate = MerchantUtils.divide(channelFeeAmount, payOrderDO.getAmount());
        }
        orderFeeResultDO.setOrderNo(payOrderDO.getPayOrderNo());
        orderFeeResultDO.setType(PayOrderEnums.ORDER_STATUS_TYPE.PAY_ORDER_STATUS.getCode());
        orderFeeResultDO.setAmount(payOrderDO.getAmount());
        orderFeeResultDO.setFeeRate(payOrderDO.getFeeRate());
        orderFeeResultDO.setFeeAmount(payOrderDO.getFeeAmount());
        orderFeeResultDO.setChannelFeeRate(channelFeeRate);
        orderFeeResultDO.setChannelFeeAmount(channelFeeAmount);
        orderFeeResultDO.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
        return orderFeeResultDO;
    }

    /**
     * 商户手续费计算
     * 
     * @param payOrderDO
     * @param merchantFeeConfig
     * @return
     */
    OrderFeeResultDO processMerchantCalculate(PayOrderDO payOrderDO, ProviderChannelFeeConfigList merchantFeeConfig) {
        if (merchantFeeConfig == null) {
            return null;
        }
        OrderFeeResultDO orderFeeResultDO = new OrderFeeResultDO();
        // 机构手续费费率
        BigDecimal channelFeeRate = null;
        // 机构交易手续费
        BigDecimal channelFeeAmount = null;
        if (CommonEnum.YES_NO_TYPE.YES.getCode().equals(merchantFeeConfig.getStepFeeType())) {
            List<StepFeeConfig> stepFeeConfigs = merchantFeeConfig.getStepFeeConfigs();
            for (StepFeeConfig stepFeeConfig : stepFeeConfigs) {
                boolean amountInRange = isAmountInRange(payOrderDO.getAmount(), stepFeeConfig.getStartAmt(), stepFeeConfig.getEndAmt());
                if (amountInRange) {
                    channelFeeRate = stepFeeConfig.getRateBase();
                    break;
                }
            }
        }
        // 最后才是基础费率
        if (channelFeeAmount == null) {
            DefaultFeeConfig defaultFeeConfigValue = merchantFeeConfig.getDefaultFeeConfigValue();
            PayEnums.FEE_TYPE feeType = PayEnums.FEE_TYPE.from(defaultFeeConfigValue.getFeeType());
            switch (feeType) {
                case FIXED_VALUE:
                    channelFeeAmount = defaultFeeConfigValue.getFixedRate();
                    break;
                case PERCENTAGE:
                    channelFeeRate = defaultFeeConfigValue.getRateBase();
                    break;
                default:
                    BigDecimal multiply = payOrderDO.getAmount().multiply(defaultFeeConfigValue.getRateBase());
                    if (multiply.compareTo(defaultFeeConfigValue.getFixedRate()) > 0) {
                        channelFeeAmount = defaultFeeConfigValue.getFixedRate();
                        channelFeeRate = defaultFeeConfigValue.getRateBase();
                    }
                    else {
                        channelFeeAmount = defaultFeeConfigValue.getFixedRate();
                    }

            }
        }
        if (channelFeeRate != null && channelFeeAmount == null) {
            channelFeeAmount = MerchantUtils.calculateFeeUp(payOrderDO.getAmount(), channelFeeRate);
        }
        if (channelFeeRate == null && channelFeeAmount != null) {
            channelFeeRate = MerchantUtils.divide(channelFeeAmount, payOrderDO.getAmount());
        }
        orderFeeResultDO.setOrderNo(payOrderDO.getPayOrderNo());
        orderFeeResultDO.setType(PayOrderEnums.ORDER_STATUS_TYPE.PAY_ORDER_STATUS.getCode());
        orderFeeResultDO.setAmount(payOrderDO.getAmount());
        orderFeeResultDO.setFeeRate(payOrderDO.getFeeRate());
        orderFeeResultDO.setFeeAmount(payOrderDO.getFeeAmount());
        orderFeeResultDO.setChannelFeeRate(channelFeeRate);
        orderFeeResultDO.setChannelFeeAmount(channelFeeAmount);
        orderFeeResultDO.setStatus(CommonEnum.YES_NO_TYPE.YES.getCode());
        return orderFeeResultDO;
    }

    public boolean isAmountInRange(BigDecimal amount, BigDecimal startAmt, BigDecimal endAmt) {
        if (amount == null || startAmt == null || endAmt == null) {
            return false; // or throw an exception based on your use case
        }
        return amount.compareTo(startAmt) >= 0 && amount.compareTo(endAmt) <= 0;
    }

    void processRefundOrder(String refundOrderNo) {
        RefundOrderDO refundOrderDO = refundOrderService.queryRefundOrder(refundOrderNo);
        if (refundOrderDO == null) {
            log.info("收到的数据错误 订单号不存在 refundOrderNo:{}", refundOrderNo);
            return;
        }
        PayOrderDO payOrderDO = payOrderService.queryPayOrder(refundOrderDO.getPayOrderNo());
        BigDecimal decimal = refundOrderDO.getRefundAmount().divide(payOrderDO.getAmount(), 4, RoundingMode.HALF_DOWN);
        // 商户手续费率增加
        merchantService.updateMerchantFeeAmount(payOrderDO.getOrderSn(), payOrderDO.getFeeAmount().multiply(decimal), CommonEnum.YES_NO_TYPE.YES);
        // 商户手续费率同步数据库
        // merchantService.syncMerchantFeeAmount(payOrderDO.getOrderSn());
        MerchantFinanceRecordReturnReq merchantFinanceRecordReturnReq = new MerchantFinanceRecordReturnReq();
        merchantFinanceRecordReturnReq.setRefundOrderNo(refundOrderNo);
        merchantFinanceRecordReturnReq.setPayOrderNo(refundOrderDO.getPayOrderNo());
        merchantFinanceRecordReturnReq.setRate(decimal);
        financeRecordAppService.returnFinanceRecord(merchantFinanceRecordReturnReq);
    }

}
